package g14.sc12project.milestone1.Warehouse;
import java.awt.image.ConvolveOp;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Warehouse implements WarehouseWS {

	@Override
	public String query(String resourceID) {
		Document doc = createDocument();
		if (doc != null) {
			Element eElement = getItem(resourceID, doc);
			if (eElement != null) {
				String value = getResourceAmount(resourceID, eElement);
				return value;
			}
		}
		return null;
	}

	@Override
	public boolean pickupItems(String resourceID, int amount) {
		Document doc = createDocument();
		Element eElement = getItem(resourceID, doc);
		boolean value = removeAmountToResource(resourceID, amount, eElement,
				doc);
		if (value)
			return value;
		else
			return false;
	}

	@Override
	public int complementStock(String resourceID, int amount) {
		Document doc = createDocument();
		Element eElement = getItem(resourceID, doc);
		if (eElement != null) {
			int value = addAmountToResource(resourceID, amount, eElement, doc);
			if (value != -1000)
				return value;
		}
		return 0;
	}
	@Override
	public String holdItems(String resourceID, int amount) {
		Document doc = createDocument();
		Element eElement = getItem(resourceID, doc);
		if (eElement != null) {
			String value = getResourceAmount(resourceID, eElement);
			if (value != null) {
				int Quantity = Integer.parseInt(value);
				if (Quantity >= amount) {
					String requestID = createHoldignRequest(resourceID, amount,
							doc);
					removeAmountToResource(resourceID, amount, eElement, doc);
					return requestID;
				} else {
					return "Not Enough Items";
				}
			}
		}
		return null;
	}

	@Override
	public void cancelHoldingItems(String holdingID) {

		Document doc = createDocument();
		Element eElement = getRequest(holdingID, doc);
		if (cancelHoldignRequest(holdingID, eElement, doc)) {

		}

	}

	@Override
	public boolean pickupHoldingItems(String holdingID) {
		Document doc = createDocument();
		Element eElement = getRequest(holdingID, doc);
		
		NodeList nlListn = eElement.getElementsByTagName("war:amount").item(0)
		.getChildNodes();
		Node nAmount = (Node) nlListn.item(0);
		
		int Amount  = Integer.parseInt(nAmount.getNodeValue());
		Node na = (Node) eElement;
		Node check = na.getParentNode().removeChild(na);
		if (na.getNodeValue() == check.getNodeValue()) {
			transform(doc);
			return true;
		} else
			return false;
	}

	private String createHoldignRequest(String resouceID, int amount,
			Document doc) {
		NodeList nHoldingRequest = doc.getElementsByTagName("war:holdingReques");
		Node HoldingReq = nHoldingRequest.item(0);
		NodeList nList = doc.getElementsByTagName("war:request");
		int NoOfRequest = nList.getLength();
		Element request = doc.createElement("war:request");
		Element requestID = doc.createElement("war:requestID");
		String reqID = null;

		if (NoOfRequest == 0) {
			reqID = "residone";
			requestID.appendChild(doc.createTextNode(reqID));
		} else {

			int RequestID = NoOfRequest + 1;
			reqID = "resid" + RequestID;
			requestID.appendChild(doc.createTextNode(reqID));
		}
		request.appendChild(requestID);

		Element item = doc.createElement("war:item");
		Element itemResourceID = doc.createElement("war:resourceID");
		itemResourceID.appendChild(doc.createTextNode(resouceID));
		item.appendChild(itemResourceID);

		Element itemAmount = doc.createElement("war:amount");
		String strAmount = Integer.toString(amount);
		itemAmount.appendChild(doc.createTextNode(strAmount));
		item.appendChild(itemAmount);

		request.appendChild(item);
		HoldingReq.appendChild(request);

		try {
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();

			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(
					new File("../datasource/ds_14_2.xml"));
			transformer.transform(source, result);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return reqID;
	}

	private boolean cancelHoldignRequest(String holdingID, Element eElement,
			Document doc) {

		NodeList nlListn = eElement.getElementsByTagName("war:amount").item(0)
				.getChildNodes();
		Node nAmount = (Node) nlListn.item(0);

		NodeList nResource = eElement.getElementsByTagName("war:resourceID")
				.item(0).getChildNodes();
		Node nResourceID = (Node) nResource.item(0);
		String strResourceID = nResourceID.getNodeValue();

		int amount = Integer.parseInt(nAmount.getNodeValue());
		Element nItem = getItem(strResourceID, doc);
		if (nItem != null) {
			int a = addAmountToResource(strResourceID, amount, nItem, doc);
		}
		Node na = (Node) eElement;
		Node check = na.getParentNode().removeChild(na);
		if (na.getNodeValue() == check.getNodeValue()) {
			transform(doc);
			return true;
		} else
			return false;
	}
	
	//For query function
	private String getResourceAmount(String resouceID, Element eElement) {
		NodeList nlListn = eElement.getElementsByTagName("war:amount").item(0)
				.getChildNodes();
		Node nAmount = (Node) nlListn.item(0);
		return nAmount.getNodeValue();
	}

	//for complement method
	private int addAmountToResource(String resouceID, int Amount,
			Element eElement, Document doc) {

		NodeList nlListn = eElement.getElementsByTagName("war:amount").item(0)
				.getChildNodes();
		Node nAmount = (Node) nlListn.item(0);
		int OldValue = Integer.parseInt(nAmount.getNodeValue());
		int NewValue = OldValue + Amount;

		nAmount.setNodeValue(Integer.toString(NewValue));
		transform(doc);
		return Integer.parseInt(nAmount.getNodeValue());
	}

	//for holdItems method
	private boolean removeAmountToResource(String resouceID, int Amount,
			Element eElement, Document doc) {
		if (eElement != null) {
			NodeList nlListn = eElement.getElementsByTagName("war:amount").item(0)
					.getChildNodes();
			Node nAmount = (Node) nlListn.item(0);
			int OldValue = Integer.parseInt(nAmount.getNodeValue());
			if (OldValue >= Amount) {
				int NewValue = OldValue - Amount;

				nAmount.setNodeValue(Integer.toString(NewValue));
				transform(doc);
				return true;
			}
		}
		return false;
	}
	//For creating the document object
	private Document createDocument() {
		try {
			File fXmlFile = new File("../datasource/ds_14_2.xml");
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(fXmlFile);
			doc.getDocumentElement().normalize();
			return doc;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	//For writing the document object to file
	private void transform(Document doc) {
		try {
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();

			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(
					new File("../datasource/ds_14_2.xml"));
			transformer.transform(source, result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//returns the single item by ResourceID
	private Element getItem(String resouceID, Document doc) {
		NodeList nList = doc.getElementsByTagName("war:item");

		for (int temp = 0; temp < nList.getLength() - 1; temp++) {

			Node nNode = nList.item(temp);

			if (nNode.getNodeType() == Node.ELEMENT_NODE) {
				Element eElement = (Element) nNode;
				NodeList nlList = eElement.getElementsByTagName("war:resourceID")
						.item(0).getChildNodes();

				Node nValue = (Node) nlList.item(0);
				String strResourceID = nValue.getNodeValue();
				if (strResourceID.compareTo(resouceID) == 0) {
					return eElement;
				}
			}
		}
		return null;
	}
	//returns the single item by RequestID
	private Element getRequest(String requestID, Document doc) {
		NodeList nList = doc.getElementsByTagName("war:request");

		for (int temp = 0; temp < nList.getLength(); temp++) {

			Node nNode = nList.item(temp);

			if (nNode.getNodeType() == Node.ELEMENT_NODE) {
				Element eElement = (Element) nNode;
				NodeList nlList = eElement.getElementsByTagName("war:requestID")
						.item(0).getChildNodes();

				Node nValue = (Node) nlList.item(0);
				String strRequestID = nValue.getNodeValue();
				if (strRequestID.compareTo(requestID) == 0) {
					return eElement;
				}
			}
		}
		return null;
	}
}
